﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using System.Reflection;

namespace UIAutomation
{
    public class UIAutomation
    {
        [DllImport("User32")]
        public extern static void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public extern static int SetWindowPos(
            IntPtr hwnd,
            IntPtr hWndInsertAfter,
            int x,
            int y,
            int cx,
            int cy,
            int wFlags
            );

        /// <summary>
        /// 正常启动一个外挂
        /// </summary>
        /// <param name="appPath">路径</param>
        /// <param name="start">是否自动开始</param>
        /// <param name="sleepTime">启动程序后离开始的间隔时间  毫秒</param>
        /// <returns>进程对象</returns>
        public static Process StartApplication(string appPath, bool start, int sleepTime)
        {
            Process proc = Process.Start(appPath);//启动进程
            if (start)
            {
                Thread.Sleep(sleepTime);//等待程序启动
                SetWindowPos(proc.MainWindowHandle, (IntPtr)(-1), 0, 0, 800, 600, 0x0100);//设置窗体位置
                KeyAndMouse.SetCursorPos(45, 34);//设置鼠标到 控制 位置
                mouse_event((int)MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);//单击
                KeyAndMouse.SetCursorPos(70, 58);
                mouse_event((int)MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);
                KeyAndMouse.SetCursorPos(204, 58);
                mouse_event((int)MouseEventFlags.LeftUp, 0, 0, 0, IntPtr.Zero);
                Thread.Sleep(500);
                KeyAndMouse.ShowWindow((int)proc.MainWindowHandle, KeyAndMouse.nCmdShow.SW_MAXIMIZE);//最小化窗体
                return proc;
            }
        }

        /// <summary>
        /// 使用代理启动一个外挂
        /// </summary>
        /// <param name="appPath">路径</param>
        /// <param name="start">是否自动开始</param>
        /// <param name="sleepTime">启动程序后离开始的间隔时间  毫秒</param>
        /// <returns>进程对象</returns>
        public static Process StartApplicationWithProxy(string appPath, bool start, int sleepTime)
        {
            Process proc = Process.Start(appPath);
            if (start)
            {
                Thread.Sleep(sleepTime);
                SetWindowPos(proc.MainWindowHandle, (IntPtr)(-1), 0, 0, 800, 600, 0x0100);
                KeyAndMouse.SetCursorPos(45, 34);
                mouse_event((int)MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);
                KeyAndMouse.SetCursorPos(70, 58);
                mouse_event((int)MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);
                KeyAndMouse.SetCursorPos(204, 83);
                mouse_event((int)MouseEventFlags.LeftUp, 0, 0, 0, IntPtr.Zero);
                SetWindowPos(proc.MainWindowHandle, (IntPtr)(-1), 300, 300, 800, 600, 0x0100);
                Thread.Sleep(500);
                KeyAndMouse.ShowWindow((int)proc.MainWindowHandle, KeyAndMouse.nCmdShow.SW_MAXIMIZE);
            }
            return proc;
        }

        /// <summary>
        /// 强制关闭进程
        /// </summary>
        /// <param name="p">进程对象</param>
        public static void KillProcess(Process p)
        {
            p.Kill();
        }
    }

    #region 封装

    #region 模拟鼠标键盘类

    /// <summary>
    /// 模拟鼠标键盘类
    /// </summary>
    class KeyAndMouse
    {
        /// <summary>
        /// Sendmessage的预定义值
        /// </summary>
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_SYSCHAR = 0X106;
        public const int WM_SYSKEYUP = 0X105;
        public const int WM_SYSKEYDOWN = 0X104;
        public const int WM_CHAR = 0X102;

        /// <summary>
        /// 加载user32.dll的PostMessage函数
        /// </summary>
        /// <param name="hWnd">目标窗口句柄</param>
        /// <param name="msg">消息类型</param>
        /// <param name="wParam">w参数</param>
        /// <param name="lParam">l参数</param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "PostMessage")]
        private static extern bool _PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam);
        public static bool PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam)
        { return _PostMessage(hWnd, msg, wParam, lParam); }

        /// <summary>
        /// 设置窗口位置
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="hWndInsertAfter"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        /// <param name="wFlags"></param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern int SetWindowPos(
            IntPtr hwnd,
            IntPtr hWndInsertAfter,
            int x,
            int y,
            int cx,
            int cy,
            int wFlags
            );

        public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
        public static readonly IntPtr HWND_TOP = new IntPtr(0);
        public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
        public const UInt32 SWP_NOSIZE = 0x0001;
        public const UInt32 SWP_NOMOVE = 0x0002;
        public const UInt32 SWP_NOZORDER = 0x0004;
        public const UInt32 SWP_NOREDRAW = 0x0008;
        public const UInt32 SWP_NOACTIVATE = 0x0010;
        public const UInt32 SWP_FRAMECHANGED = 0x0020;  /* The frame changed: send WM_NCCALCSIZE */
        public const UInt32 SWP_SHOWWINDOW = 0x0040;
        public const UInt32 SWP_HIDEWINDOW = 0x0080;
        public const UInt32 SWP_NOCOPYBITS = 0x0100;
        public const UInt32 SWP_NOOWNERZORDER = 0x0200;  /* Don't do owner Z ordering */
        public const UInt32 SWP_NOSENDCHANGING = 0x0400;  /* Don't send WM_WINDOWPOSCHANGING */

        public const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
        /// <summary>
        /// 查找窗口句柄
        /// </summary>
        /// <param name="lpClassName"></param>
        /// <param name="lpWindowName"></param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern int FindWindow(
            string lpClassName,
            string lpWindowName
            );

        /// <summary>
        /// 重载Sendmessage函数
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="Msg">所有msg的值见参考资料</param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, string lParam);

        /// <summary>
        /// 设置windows的标题
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="lpString">要修改的字符串指针</param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern bool SetWindowText(IntPtr hWnd, string lpString);

        /// <summary>
        /// 用于输入账号名，密码和角色名的函数
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="Input">输入字符串</param>
        public static void InputStr(IntPtr hWnd, string Input)
        {
            byte[] ch = (Encoding.ASCII.GetBytes(Input));
            for (int i = 0; i < ch.Length; i++)
            {
                PostMessage(hWnd, WM_CHAR, ch[i], 0);
            }
        }

        /// <summary>
        /// 获取当前激活窗体的标题
        /// </summary>
        /// <returns>窗体的标题</returns>
        public static String GetActiveWindowText()
        {
            StringBuilder str = new StringBuilder(512);
            GetWindowText((int)GetActiveWindow(), str, str.Capacity);
            return str.ToString();
        }

        /// <summary>
        /// 获取指定窗体的标题
        /// </summary>
        /// <returns>窗体的标题</returns>
        public static String GetWindowText(IntPtr pWindow)
        {
            StringBuilder str = new StringBuilder(512);
            GetWindowText((int)pWindow, str, str.Capacity);
            return str.ToString();
        }

        #region Windows Api 定义

        /// 
        /// 模拟鼠标事件
        /// 
        /// 鼠标事件的Enum
        /// X座标
        /// Y座标
        /// 
        [DllImport("user32.dll")]
        public static extern void mouse_event(MouseEvents dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);

        /// 
        /// 定义模拟鼠标的常数
        /// 
        public enum MouseEvents : uint
        {
            MOUSEEVENTF_LEFTDOWN = 0x2,
            MOUSEEVENTF_LEFTUP = 0x4,
            MOUSEEVENTF_MIDDLEDOWN = 0x20,
            MOUSEEVENTF_MIDDLEUP = 0x40,
            MOUSEEVENTF_MOVE = 0x1,
            MOUSEEVENTF_ABSOLUTE = 0x8000,
            MOUSEEVENTF_RIGHTDOWN = 0x8,
            MOUSEEVENTF_RIGHTUP = 0x10,
        }

        /// 
        /// 根据窗口句柄，获得窗口的类名
        /// 
        /// 窗口句柄
        /// 缓冲区
        /// 最大字节数
        /// 整型，代表类名
        [DllImport("user32.dll")]
        public static extern int GetClassName(int hwnd, StringBuilder buf, int nMaxCount);

        /// 
        /// 根据窗口句柄，获得指定窗口的标题。
        /// 
        /// 窗口句柄
        /// 缓冲区
        /// 最大字节数
        /// 返回标题
        [DllImport("user32.dll")]
        public static extern int GetWindowText(int hwnd, StringBuilder buf, int nMaxCount);

        /// 
        /// 根据窗口句柄，设置指定窗口为前置窗口。
        /// 
        /// 窗口句柄
        [DllImport("user32.dll")]
        public static extern void SetForegroundWindow(IntPtr hwnd);

        /// 
        /// 根据窗口句柄和显示的样式，显示窗口。
        /// 
        /// 窗口句柄
        /// 显示窗口的样式。
        /// 成功与否。
        [DllImport("user32.dll")]
        public static extern bool ShowWindow(int hWnd, nCmdShow nCmdShow);
        public enum nCmdShow : uint
        {
            SW_FORCEMINIMIZE = 0x0,
            SW_HIDE = 0x1,
            SW_MAXIMIZE = 0x2,
            SW_MINIMIZE = 0x3,
            SW_RESTORE = 0x4,
            SW_SHOW = 0x5,
            SW_SHOWDEFAULT = 0x6,
            SW_SHOWMAXIMIZED = 0x7,
            SW_SHOWMINIMIZED = 0x8,
            SW_SHOWMINNOACTIVE = 0x9,
            SW_SHOWNA = 0xA,
            SW_SHOWNOACTIVATE = 0xB,
            SW_SHOWNORMAL = 0xC,
        }

        /// 
        /// 捕捉当前鼠标位置
        /// 
        /// 传入参数，代表鼠标的当前位置
        /// 
        [DllImport("user32.dll")]
        public static extern long GetCursorPos(ref Point lpPoint);

        /// <summary>
        /// 获取激活窗体的句柄
        /// </summary>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetActiveWindow();

        #endregion


        /// <summary>
        /// 打开和关闭CD托盘.
        /// </summary>
        [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
        public static extern int mciSendString(string lpstrCommand, string lpstrReturnstring, int uReturnLength, int hwndCallback);

        /// <summary>
        /// 显示和隐藏鼠标指针.
        /// </summary>
        [DllImport("user32.dll", EntryPoint = "ShowCursor", CharSet = CharSet.Auto)]
        public static extern int ShowCursor(int bShow);
        /// <summary>
        /// 清空回收站.
        /// </summary>
        [DllImport("shell32.dll", EntryPoint = "SHEmptyRecycleBin", CharSet = CharSet.Auto)]
        public static extern long SHEmptyRecycleBin(IntPtr hwnd, string pszRootPath, long dwFlags);
        /// <summary>
        /// 打开浏览器
        /// </summary>
        [DllImport("shell32.dll", EntryPoint = "ShellExecute", CharSet = CharSet.Auto)]
        public static extern int ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
        /// <summary>
        /// 最大化窗口，最小化窗口，正常大小窗口；
        /// </summary>
        [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
        public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
        //最大化窗口：
        //ApiCalls.ShowWindow(Form.ActiveForm.Handle,3);
        //最小化窗口：
        //ApiCalls.ShowWindow(Form.ActiveForm.Handle,2);
        //恢复正常大小窗口：
        //ApiCalls.ShowWindow(Form.ActiveForm.Handle,1);

        /// <summary>
        /// 设置鼠标位置
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int X, int Y);

        /// <summary>
        /// 模仿键盘操作
        /// </summary>
        /// <param name="vk"></param>
        /// <param name="scan"></param>
        /// <param name="flags"></param>
        /// <param name="extrainfo"></param>
        [DllImport("user32.dll", EntryPoint = "keybd_event", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern void Keybd_event(byte vk, byte scan, int flags, int extrainfo);

        public static int KEYEVENTF_EXTENDEDKEY = 0x0001;
        public static int KEYEVENTF_KEYUP = 0x0002;
        public static byte VK_LWIN = 0x5B;

        /// <summary>
        /// 最小化窗口
        /// </summary>
        public static void ToggleDesktop()
        {
            Keybd_event(VK_LWIN, (byte)0, KEYEVENTF_EXTENDEDKEY | 0, 0);
            Keybd_event((byte)'D', (byte)0, 0, 0);
            Keybd_event((byte)'D', (byte)0, KEYEVENTF_KEYUP, 0);
            Keybd_event(VK_LWIN, (byte)0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }

        /// <summary>
        /// 避免AFK
        /// </summary>
        public static void AntiAFK()
        {
            Keybd_event((byte)'C', (byte)0, 0, 0);
            Keybd_event((byte)'C', (byte)0, KEYEVENTF_KEYUP, 0);

        }
    }

    #endregion

    #region RECT结构

    /// <summary>
    /// 说明暂略
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    #endregion

    /// <summary>
    /// 标准发送类
    /// </summary>
    internal class Sender
    {
        /// <summary>
        /// 标准发送类
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="Msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        /// <summary>
        /// 发送字符串
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="Msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);

        /// <summary>
        /// 发送字符串
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="Msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, String lParam);

        /// <summary>
        /// 发送方向
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        internal static extern void SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref RECT lParam);

        /// <summary>
        /// 发送坐标
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref Point lParam);

        /// <summary>
        /// 另外一个标准发送类
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="Msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);


        public const uint WM_SETTEXT = 0x0C;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, bool wParam, string lParam);
    }

    /// <summary>
    /// 鼠标事件枚举
    /// </summary>
    public enum MouseEventFlags
    {
        Move = 0x0001,
        LeftDown = 0x0002,
        LeftUp = 0x0004,
        RightDown = 0x0008,
        RightUp = 0x0010,
        MiddleDown = 0x0020,
        MiddleUp = 0x0040,
        Wheel = 0x0800,
        Absolute = 0x8000
    }

    #endregion
}
